﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Frankfort.Threading.Internal;
using System.IO;


public static class Il2cppPatchDownloadManager
{
	enum State
	{
		None,
		Download,
		Decompress,
		Success,
		Failed,
	}

    static object downloadObj;
    static System.Action<bool> callback;

    static string[] urls;
	static string fileName;
	static uint size;
	
	static string md5;
    static int version;
	static int min_app_version;
    
	static State state = State.None;
	
	static string downloadCachePath;
	static int decompressProgress;
	static int decompressTotal;

    public static bool Start(string[] _urls, HttpRedirectHelper redirectHelper, string _fileName, uint _size, System.Action<bool> _callback)
    {
        if (string.IsNullOrEmpty(_fileName) || _size == 0 || _urls == null || _urls.Length <= 0)
        {
			return false;
        }
		
		string tempFileName = System.IO.Path.GetFileNameWithoutExtension(_fileName);
		
		string[] strs = tempFileName.Split('_');
		string newMd5 = strs[strs.Length - 3];
		
		if(newMd5 == md5 && state == State.Success)
		{
			if(_callback != null)
			{
				_callback(true);
			}
			return true;
		}
		
		if(callback != null)
		{
			return false;
		}
		
		
		state = State.None;
		urls = _urls;
		fileName = _fileName;
		size = _size;
		callback = _callback;
		md5 = newMd5;
		decompressProgress = 0;
		decompressTotal = 0;
		
		version = int.Parse(strs[strs.Length - 2]);
		min_app_version = int.Parse(strs[strs.Length - 1]);
		
		downloadCachePath = AndroidHelper.GetIl2cppPatchResourceCachePath();
		CommonUtil.Delete(downloadCachePath);
		CommonUtil.CreateDir(downloadCachePath);
		
		state = State.Download;
		downloadObj = HttpDownloadManager.instance.Download(urls[0] + "/" + VersionEx.compile_type + "/" + fileName, md5, size, size, CompressType.NONE, downloadCachePath + "/" + fileName, redirectHelper, OnDownloadComplete);
		return true;
	}

	public static string GetMd5()
	{
		return AndroidHelper.GetIl2cppPatchMd5();
	}

    public static uint GetProgress()
    {
		uint downloadProgress = 0;
		if(state == State.Download)
		{
			downloadProgress = (uint)HttpDownloadManager.instance.getRequestProgress(downloadObj) / 2;
		}
        else
		{
			downloadProgress = size / 2;
		}
		
		if(decompressProgress == 0)
		{
			return downloadProgress;
		}
		else
		{
			return downloadProgress + (uint)decompressProgress  * (size - downloadProgress) / (uint)decompressTotal;
		}
    }
	
	public static uint GetTotalSize()
    {
        return size;
    }

    static void OnDownloadComplete(string url, string localPath, DownloadError status)
    {
        var _callback = callback;
        
        downloadObj = null;
        if (status != DownloadError.None)
        {
			state = State.Failed;
			callback = null;
            _callback(false);
        }
        else
        {
			state = State.Decompress;
            Decompress();
        }
    }
	
	static void DecompressProgressCallback(int progress, int total)
	{
		decompressProgress = progress;
		decompressTotal = total;
	}
	
	static void Decompress()
	{
		string destPath = AndroidHelper.GetIl2cppPatchCachePath();
		
		SingleThreadStarter.StartSingleThread(() =>
		{
			bool result = true;
			CommonUtil.CreateDir(destPath);
			
			ZipHelper.UnZip(downloadCachePath + "/" + fileName, destPath, "", true, DecompressProgressCallback);

			//3. prepare libil2cpp, unzip with name: libil2cpp.so.new
			string zipLibil2cppPath = destPath + "/lib_" + Bootstrap.get_arch_abi() + "_libil2cpp.so.zip";
			if (!File.Exists(zipLibil2cppPath))
			{
				result = false;
			}
			
			if(result)
			{
				ZipHelper.UnZip(zipLibil2cppPath, destPath, "", true, null);
			}

			MainThreadDispatcher.DispatchToMainThread(() =>
				{
					state = result? State.Success: State.Failed;
					
					if(result)
					{
						AndroidHelper.SaveIl2cppPatchConfig(downloadCachePath, md5, version, min_app_version);
					}
					
					var _callback = callback;
					callback = null;
					_callback(result);
				});
		});
						

	}

}
